/** ********************************************************
 *   describe: 工具函数模块
 *   creater:
 *   date: 2021/08/12
 */
import {CHAR_GROUP_MODE} from "../consts/consts";
import Filter from "./filter";
import * as rfdc from "rfdc";
import * as moment from "moment";
import {logger} from "./logger";

export default class Utils {

    /**
     *  异步函数封装返回promise对象，
     * @param func
     * @param args
     * @returns {Promise}
     */
    public static promisefy(func: Function, ...args: any): Promise<any> {

        let promise = new Promise<any>((resolve, reject) => func(...args, (err, res) => {
            if (err) {
                reject(err);
            } else {
                resolve(res);
            }
        }));
        // 有异常则抛出undefined ，否则返回数据
        return promise
            .then((data) => {return data})
            .catch((error) => {
                logger.info(`db error --> ` , error);
                return undefined;
            })
    };


    /**
     * 取随机数（min, max）
     * @param min
     * @param max
     * @returns {*}
     */
    public static rand(min: number, max: number) {
        let n = max - min;
        return min + Math.round(Math.random() * n);
    };


    /**
     * 检查昵称合法性
     * @param nickname
     * @param nicknameArr
     * @returns {any}
     */
    public static checkNickname(nickname, nicknameArr) {

        let self = this;
        // 昵称不合法
        if (nickname === '' || typeof nickname !== 'string') {
            return 500;
        }
        // 昵称重复了
        if (nicknameArr.indexOf(nickname) !== -1) {
            return 500;
        }
        // 敏感词检查
        let checkErr = this.checkContent(nickname);
        if (checkErr) {
            return checkErr;
        }

        return undefined;
    }


    /**
     * 检查字符串合法性，用于角色和公会等名称命名使用
     * @param content 检测内容
     * @param lenArr 默认检测角色昵称，表示命名的最短和最长值
     * @param mode 默认中文+英文；有需求的扩展可以自行扩展
     * @returns {*}
     */
    public static checkContent(content, lenArr = [], mode = CHAR_GROUP_MODE.chSubEn) {

        let self = this;
        // 检查字符合法性
        if (!self.checkChar(content, mode)) {
            return 500;
        }

        let lenArrBack: number[];
        // 检查长度,默认角色的创建长度
        if (lenArr.length <= 0) {
            // let roleConstCfg = dataApi.getRoleConst();
            // lenArr = roleConstCfg.nicknameLen;
            lenArrBack = [4, 12];
        }

        let totalLen = self.clcStrLen(content);
        if (totalLen < lenArrBack[0] || totalLen > lenArrBack[1]) {
            return 500;
        }

        // 检查铭感词
        if (!Filter.filterCheck(content)) {
            return 500;
        }
        return undefined;
    }


    /**
     * 多模式检查字符串包含内容
     * @param str
     * @param mode 默认中文+英文；有需求的扩展可以自行扩展
     * @returns {boolean}
     */
    public static checkChar(str: string, mode = CHAR_GROUP_MODE.chSubEn) {


        let self = this;
        if (typeof str !== 'string') {
            return false;
        }
        let pattern = /[a-zA-Z\u4E00-\u9FA5]/;// 默认中文+英文
        if (mode === CHAR_GROUP_MODE.ch) { // 纯中文
            pattern = /[\u4E00-\u9FA5]/;
        } else if (mode === CHAR_GROUP_MODE.en) { // 纯英文
            pattern = /[a-zA-Z]/;
        } else if (mode === CHAR_GROUP_MODE.num) { // 纯数字
            pattern = /[0-9]/;
        } else if (mode === CHAR_GROUP_MODE.chSubNum) { // 中文+数字
            pattern = /[0-9\u4E00-\u9FA5]/;
        } else if (mode === CHAR_GROUP_MODE.enSubNum) { // 英文+数字
            pattern = /[a-zA-Z0-9]/;
        } else if (mode === CHAR_GROUP_MODE.chSubEnSubNum) { // 中文+英文+数字
            pattern = /[a-zA-Z0-9\u4E00-\u9FA5]/;
        } else if (mode === CHAR_GROUP_MODE.commonEmoji) { // emoji表情符号
            return !self.checkEmoji(str);
        }
        for (let i = 0; i < str.length; i++) {
            let c = str.charAt(i);
            if (!pattern.test(c)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断文本中是否有emoji表情符号
     * @param content
     * @returns {boolean}
     */
    public static checkEmoji(content: string) {
        for (let i = 0; i < content.length; i++) {
            let hs = content.charCodeAt(i);
            if (hs >= 0xd800 && hs <= 0xdbff) {
                if (content.length > 1) {
                    let ls = content.charCodeAt(i + 1);
                    let uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (uc >= 0x1d000 && uc <= 0x1f77f) {
                        return true;
                    }
                }
            } else if (content.length > 1) {
                let ls = content.charCodeAt(i + 1);
                if (ls === 0x20e3) {
                    return true;
                }
            } else {
                if (hs >= 0x2100 && hs <= 0x27ff) {
                    return true;
                }
                if (hs >= 0x2B05 && hs <= 0x2b07) {
                    return true;
                }
                if (hs >= 0x2934 && hs <= 0x2935) {
                    return true;
                }
                if (hs >= 0x3297 && hs <= 0x3299) {
                    return true;
                }
                if (hs === 0xa9 || hs === 0xae || hs === 0x303d || hs === 0x3030
                    || hs === 0x2b55 || hs === 0x2b1c || hs === 0x2b1b
                    || hs === 0x2b50) {
                    return true;
                }
            }
        }
        return false;
    };


    /**
     * 检查字符串占位符，中文算2，英文算1，数字算1
     * @param str
     * @returns {number}
     */
    public static clcStrLen(str: string) {

        let totalLen = 0;
        let patternEnSubNum = /[a-zA-Z0-9]/;// 英文+数字
        for (let i = 0; i < str.length; i++) {
            let char = str.charAt(i);
            if (patternEnSubNum.test(char)) {
                totalLen += 1;
            } else { // 其他默认2个位置
                totalLen += 2;
            }
        }
        return totalLen;
    };


    /**
     * 获取当前时间
     * @param toMs true 毫秒级别，false秒级别
     * @param getFormatStr getFormatStr 按标准格式返回字符串
     * @returns {*}
     */
    public static getCurTime(toMs: boolean = true, getFormatStr: boolean = false) {
        let curTime = new Date().getTime();// 毫秒
        if (getFormatStr) {
            let curTimeStr = '';
            if (toMs) {
                curTimeStr = `${moment(curTime).format('YYYY-MM-DD HH:mm:ss')}:${moment(curTime).milliseconds()}`;
            } else {
                curTimeStr = moment(curTime).format('YYYY-MM-DD HH:mm:ss');
            }
            return curTimeStr;
        }
        return toMs ? curTime : Math.floor(curTime / 1000);
    };

    /**
     * 获取当前月份
     * @returns {number}
     */
    public static getMonth() {
        return new Date().getMonth() + 1;
    };

    /**
     * 获取当前日期天数
     * @returns {number}
     */
    public static getDay() {
        return new Date().getDate();
    };

}
